package com.navi.loaddata.loadService.impl.measureData;

import com.navi.loaddata.core.errorLog.ErrorCode;
import com.navi.loaddata.core.etlException.ETLException2;
import com.navi.loaddata.core.gpEntity.*;
import com.navi.loaddata.core.gpEntity.array.WppAdefectF;
import com.navi.loaddata.core.gpEntity.array.WppAdefectGlassF;
import com.navi.loaddata.core.gpEntity.array.WppAdefectPanelF;
import com.navi.loaddata.core.gpEntity.cf.WppFdefectF;
import com.navi.loaddata.core.gpEntity.cf.WppFdefectGlassF;
import com.navi.loaddata.core.gpEntity.cf.WppFdefectPanelF;
import com.navi.loaddata.core.gpEntity.oc.WppCdefectF;
import com.navi.loaddata.core.gpEntity.oc.WppCdefectGlassF;
import com.navi.loaddata.core.gpEntity.oc.WppCdefectPanelF;
import com.navi.loaddata.core.mysqlEntity.EdaMeasureDefecttypeD;
import com.navi.loaddata.core.mysqlEntity.EtlConfD;
import com.navi.loaddata.core.mysqlEntity.EtlConfDModel;
import com.navi.loaddata.core.repository.impl.GreenPlumRepositoryImpl;
import com.navi.loaddata.core.repository.impl.MySqlRepositoryImpl;
import com.navi.loaddata.core.util.LoggerUtil;
import com.navi.loaddata.core.util.ProcessUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.navi.loaddata.core.constant.GenericDef.*;
import static java.util.stream.Collectors.groupingBy;

@Service
@Transactional(transactionManager = "secondaryPlatformTransactionManager")
public class LoadDefectInfoService {
    private static final Logger logger = LoggerFactory.getLogger(LoadDefectInfoService.class);
    private LoggerUtil loggerUtil = new LoggerUtil(this.getClass());

    private static final Map<String, String> glassNameMap;
    private static final Map<String, String> glassEntityNameMap;

    static {
        glassNameMap = new HashMap<>();
        glassNameMap.put(SHOP_ARY, "sor.wpp_adefect_glass_f");
        glassNameMap.put(SHOP_CF, "sor.wpp_fdefect_glass_f");
        glassNameMap.put(SHOP_OC, "sor.wpp_cdefect_glass_f");

        glassEntityNameMap = new HashMap<>();
        glassEntityNameMap.put(SHOP_ARY, "WppAdefectGlassF");
        glassEntityNameMap.put(SHOP_CF, "WppCdefectGlassF");
        glassEntityNameMap.put(SHOP_OC, "WppFdefectGlassF");
    }

    @Autowired
    private GreenPlumRepositoryImpl dao2;
    @Autowired
    private MySqlRepositoryImpl mysqlDao;

    public List<GpGlassF> loadGlassInfo(EtlConfDModel etlConfD) throws Exception {
        List<GpGlassF> glassList = new ArrayList<>();
        StringBuffer hql = new StringBuffer();
        StringBuffer hql2 = new StringBuffer();
        hql2.append("WHERE 1=1 ")
                .append(" and dbTimestamp >= '").append(etlConfD.getRunStartTimestamp())
                .append("' and dbTimestamp<'").append(etlConfD.getRunEndTimestamp())
                .append("' and realFlg='Y' ")
                .append(ProcessUtil.getOpeHql(etlConfD.getOpe()))
                .append(ProcessUtil.getEqptHql(etlConfD.getEqpt()));
        try {
            switch (etlConfD.getShop()) {
                case "ARRAY":
                    hql.append("FROM WppAdefectGlassF ").append(hql2).append(" and glassId like 'A%'")
                            .append(" and length(glassId)=10");

                    glassList = GpGlassFMapper.INSTANCE.arrayToEtlGlass(dao2.list(WppAdefectGlassF.class, hql.toString()));
                    break;
                case "CF":
                    hql.append("FROM WppFdefectGlassF ").append(hql2).append(" and glassId like 'C%'")
                            .append(" and length(glassId)=10");

                    glassList = GpGlassFMapper.INSTANCE.cfToEtlGlass(dao2.list(WppFdefectGlassF.class, hql.toString()));
                    break;
                case "OC":
                    if ("CELL1".equals(etlConfD.getCellType())) {
                        hql.append("FROM WppCdefectGlassF ").append(hql2).append(" and (glassId like 'A%' or glassId like 'C%')")
                                .append(" and length(glassId)=10")
                                .append(" and opeId<'L4600' ");

                        glassList = GpGlassFMapper.INSTANCE.cellToEtlGlass(dao2.list(WppCdefectGlassF.class, hql.toString()));
                    } else if ("CELL2".equals(etlConfD.getCellType())) {
                        hql.append("FROM WppCdefectGlassF ").append(hql2).append(" and glassId like 'A%'")
                                .append(" and length(glassId)=12");
                        glassList = GpGlassFMapper.INSTANCE.cellToEtlGlass(dao2.list(WppCdefectGlassF.class, hql.toString()));
                    } else {
                        throw new ETLException2(ErrorCode.ERROR_CELL_TYPE, null);
                    }
                    break;
                default:
                    throw new ETLException2(ErrorCode.ERROR_SHOP, null);
            }
        } catch (Exception e) {
            throw new ETLException2(ErrorCode.ERROR_GET_GP_GLASS, e);
        }
        List<GpGlassF> glassList2 = new ArrayList<>();
        for (GpGlassF glass : glassList) {
            if (glass.getGlassId().length() < 10) {
                logger.warn("glassId={} opeId={} procEndTime={} 数据不合规范!跳过!", glass.getGlassId(), glass.getOpeId(), glass.getEvtTimestamp());
                continue;
            }
            glassList2.add(glass);
        }
        return glassList2;
    }

    public Map<String, List<GpChipF>> loadPanelInfo(EtlConfDModel etlConfD, List<GpGlassF> glassList) throws Exception {
        List<GpChipF> chipList = new ArrayList<>();
        Map<String, List<GpChipF>> chipListMap = new HashMap<>();
        int i = 0;
        StringBuffer hql = new StringBuffer();
        StringBuffer hql2 = new StringBuffer();
        hql2.append(" where 1=1 and (");
        for (GpGlassF glass : glassList) {
            //站点限制
            if (true == (ProcessUtil.opeLimit(glass.getOpeId()))) {
                chipListMap.put(glass.getUnqSeqId(), null);
                continue;
            }
            hql2.append("(1=1 AND opeId='" + glass.getOpeId() + "'")
                    .append(" and evtTimestamp='" + glass.getEvtTimestamp() + "'")
                    .append(" and realFlg='" + glass.getRealFlg() + "'")
                    .append(" and glassId='" + glass.getGlassId() + "'")
                    .append(" and jgeCnt='" + glass.getJgeCnt() + "')")
                    .append(" or");
        }
        ;
        hql2.deleteCharAt(hql2.length() - 1);
        hql2.deleteCharAt(hql2.length() - 1);
        hql2.append(")");
        try {
            //sql from table where (ope,evttime,realflg,glassId,jgecnt) in((...),(...),(...))
            switch (etlConfD.getShop()) {
                case "ARRAY":
                    hql.append(" FROM WppAdefectPanelF ").append(hql2);
                    chipList = GpChipFMapper.INSTANCE.arrayToEtlChip(dao2.list(WppAdefectPanelF.class, hql.toString()));
                    break;
                case "CF":
                    hql.append("FROM WppFdefectPanelF ").append(hql2);
                    chipList = GpChipFMapper.INSTANCE.cfToEtlChip(dao2.list(WppFdefectPanelF.class, hql.toString()));
                    break;
                case "OC":
                    hql.append("FROM WppCdefectPanelF ").append(hql2);
                    chipList = GpChipFMapper.INSTANCE.cellToEtlChip(dao2.list(WppCdefectPanelF.class, hql.toString()));
                    break;
                default:
                    throw new ETLException2(ErrorCode.ERROR_SHOP);
            }
        } catch (Exception e) {
            throw new ETLException2(ErrorCode.ERROR_GET_GP_PANEL, e);
        }
        for (GpChipF chip : chipList) {
            if (chip.getPanelId().contains("*")) {
                logger.warn("glassId={},opeId={},procEndTime={}存在panelId包含*,跳过处理!", chip.getGlassId(), chip.getOpeId(), chip.getProcEndTime().toString());
                continue;
            }
            if (chip.getPanelId().length() != 12) {
                logger.warn("glassId={},opeId={},procEndTime={} panelId不是12码,跳过处理!", chip.getGlassId(), chip.getOpeId(), chip.getProcEndTime().toString());
                continue;
            }
            if (null == chipListMap.get(chip.getUnqSeqId())) {
                List<GpChipF> list = new ArrayList<>();
                list.add(chip);
                chipListMap.put(chip.getUnqSeqId(), list);
            } else {
                chipListMap.get(chip.getUnqSeqId()).add(chip);
            }
        }
        return chipListMap;
    }

    public Map<String, List<GpDefectF>> loadDefectInfo(EtlConfDModel etlConfD, List<GpGlassF> glassList) throws Exception {
        List<GpDefectF> defectList = new ArrayList<>();
        Map<String, List<GpDefectF>> defectListMap = new HashMap<>();
        int i = 0;
        StringBuffer hql = new StringBuffer();
        StringBuffer hql2 = new StringBuffer();
        hql2.append(" where 1=1 and (");
        for (GpGlassF glass : glassList) {
            //站点限制
            if (true == (ProcessUtil.opeLimit(glass.getOpeId()))) {
                continue;
            }
            hql2.append("(1=1 AND opeId='" + glass.getOpeId() + "'")
                    .append(" and evtTimestamp='" + glass.getEvtTimestamp() + "'")
                    .append(" and realFlg='" + glass.getRealFlg() + "'")
                    .append(" and glassId='" + glass.getGlassId() + "'")
                    .append(" and jgeCnt='" + glass.getJgeCnt() + "')")
                    .append(" or");
        }
        ;
        hql2.deleteCharAt(hql2.length() - 1);
        hql2.deleteCharAt(hql2.length() - 1);
        hql2.append(")");
        try {
            switch (etlConfD.getShop()) {
                case "ARRAY":
                    hql.append("FROM WppAdefectF ").append(hql2);
                    defectList = GpDefectFMapper.INSTANCE.arrayToEtlDefect(dao2.list(WppAdefectF.class, hql.toString()));
                    break;
                case "CF":
                    hql.append("FROM WppFdefectF ").append(hql2);
                    defectList = GpDefectFMapper.INSTANCE.cfToEtlDefect(dao2.list(WppFdefectF.class, hql.toString()));
                    break;
                case "OC":
                    hql.append("FROM WppCdefectF ").append(hql2);
                    defectList = GpDefectFMapper.INSTANCE.cellToEtlDefect(dao2.list(WppCdefectF.class, hql.toString()));
                    break;
                default:
                    throw new ETLException2(ErrorCode.ERROR_SHOP);
            }
        } catch (Exception e) {
            throw new ETLException2(ErrorCode.ERROR_GET_GP_DEFECT, e);
        }
        for (GpDefectF defect : defectList) {
            if (defect.getPanelId().contains("*")) {
                logger.warn("glassId={},defectNo={},opeId={},procEndTime={}存在panelId包含*,跳过处理!", defect.getGlassId(), defect.getDefectNo(), defect.getOpeId(), defect.getProcEndTime().toString());
                continue;
            }
            if (defect.getPanelId().length() != 12) {
                logger.warn("glassId={},defectNo={},opeId={},procEndTime={} panelId不是12码,跳过处理!", defect.getGlassId(), defect.getDefectNo(), defect.getOpeId(), defect.getProcEndTime().toString());
                continue;
            }
            if (null == defectListMap.get(defect.getUnqSeqId())) {
                List<GpDefectF> list = new ArrayList<>();
                list.add(defect);
                defectListMap.put(defect.getUnqSeqId(), list);
            } else {
                defectListMap.get(defect.getUnqSeqId()).add(defect);
            }
        }
        return defectListMap;
    }


    public Map<String, String> loadMOpeDInfo(EtlConfDModel etlConfD) {
        Map<String, String> mapOpe = new HashMap<>();
        List<MOpeD> opeList = new ArrayList<>();
        StringBuffer hql = new StringBuffer();
        hql.append("FROM MOpeD WHERE 1=1 ");
//        hql.append(ProcessUtil.getOpeHql(etlConfD.getOpe()));
        hql.append(" order by evtTimestamp");
        opeList = dao2.list(MOpeD.class, hql.toString());

        opeList.forEach(opeFormat -> {
            if (!StringUtils.isEmpty(opeFormat.getOpeDefFormat())) {
                mapOpe.put(opeFormat.getOpeId(), opeFormat.getOpeDefFormat());
            } else {
                mapOpe.put(opeFormat.getOpeId(), null);
            }
        });
        return mapOpe;
    }


    public HashMap<String, List<MppLayoutPnlD>> big2small(List<GpGlassF> defectGlassList) throws Exception {
        HashMap<String, List<MppLayoutPnlD>> glass2Map = new HashMap<>();

        Map<String, List<GpGlassF>> glassDataTree =
                defectGlassList.stream().collect(groupingBy(GpGlassF::getProdId));
        for (Map.Entry<String, List<GpGlassF>> entry : glassDataTree.entrySet()) {
            List<GpGlassF> glassList = entry.getValue();
            String layoutId;
            List<MProdD> mProdD = dao2.find(MProdD.class, "FROM MProdD where shopId='OC' and prodId='" + glassList.get(0).getProdId() + "'");
            if (mProdD.size() == 0 || StringUtils.isEmpty(mProdD.get(0).getLayoutId())) {
                glass2Map.put(glassList.get(0).getGlassId(), null);
            } else {
                layoutId = mProdD.get(0).getLayoutId();
                List<MppLayoutPnlD> layoutPnlDS = dao2.list(MppLayoutPnlD.class, "FROM MppLayoutPnlD WHERE layoutId = '" + layoutId + "'");
                glassList.forEach(glass -> {
                    glass2Map.put(glass.getGlassId(), layoutPnlDS);
                });
            }
        }
        return glass2Map;
    }

    public HashMap<String, List<MppLayoutPnlD>> small2big(List<GpGlassF> defectGlassList) throws Exception {
        HashMap<String, List<MppLayoutPnlD>> glass2Map = new HashMap<>();
        HashMap<String, String> panel2Glass = new HashMap<>();

        try {
            Map<String, List<GpGlassF>> panelDataTree =
                    defectGlassList.stream().collect(groupingBy(GpGlassF::getGlassId));
            for (Map.Entry<String, List<GpGlassF>> entry : panelDataTree.entrySet()) {
                List<GpGlassF> panelList = entry.getValue();
                panel2Glass.put(panelList.get(0).getGlassId().substring(0, 10), "glassId");
            }
            for (String key : panel2Glass.keySet()) {
                String layoutId;
                String sql = "select b.layout_Id" +
                        " from wpp_sht_info a" +
                        " left join M_Prod_D b on b.shop_Id='ARRAY' and a.product_id_ary=b.prod_id" +
                        " where a.panel_id='" + key + "' and b.shop_id is not null" +
                        " limit 1";
                List<String> layoutIdList = dao2.findBySQL(sql);
                if (layoutIdList.size() == 0 || StringUtils.isEmpty(layoutIdList.get(0))) {//默认495
                    List<MppLayoutPnlD> layoutPnlDS = dao2.list(MppLayoutPnlD.class, "FROM MppLayoutPnlD WHERE layoutId = 'ACF&A1495A1ANK1&00001'");
                    glass2Map.put(key, layoutPnlDS);
                } else {
                    layoutId = layoutIdList.get(0).toString();
                    List<MppLayoutPnlD> layoutPnlDS = dao2.list(MppLayoutPnlD.class, "FROM MppLayoutPnlD WHERE layoutId = '" + layoutId + "'");
                    glass2Map.put(key, layoutPnlDS);
                }
            }
        }catch (Exception e){
            throw new ETLException2(ErrorCode.ERROR_GET_GP_LAYOUT, e);
        }
        return glass2Map;
    }

    public List<String> getDistinctOpes(EtlConfD etlConfD) {
        List<String> opes = new ArrayList<>();
        StringBuffer opeSql = new StringBuffer();
        opeSql.append("select distinct ope_id from ");
        try {
            switch (etlConfD.getShop()) {
                case "ARRAY":
                    opeSql.append("wpp_adefect_glass_f where db_timestamp>='" + etlConfD.getRunStartTimestamp() + "'")
                            .append(" and db_timestamp<'" + etlConfD.getRunEndTimestamp() + "'");
                    break;
                case "CF":
                    opeSql.append("wpp_fdefect_glass_f where db_timestamp>='" + etlConfD.getRunStartTimestamp() + "'")
                            .append(" and db_timestamp<'" + etlConfD.getRunEndTimestamp() + "'")
                            .append(" and ope_id not in('C0000','C1110','C1150','C1151','C1160','C116J','C1300','C1310','C1311','C1330','C1341','C1351','C1353','C1380','C13A0','C13B0','C1550','C1560','C1563','C156J','C1570','C1571','C157J','C1590','C159i','C159I','C2310','C2311','C2330','C2341','C2351','C2353','C23A0','C2550','C2560','C2563','C256J','C2570','C2571','C2910','C2950','C2960','C2963','C296J','C3300','C3310','C3311','C3341','C3351','C3353','C33A0','C3550','C3560','C3563','C356J','C3590','C359I','C4310','C4311','C4341','C4351','C4353','C43A0','C4550','C4555','C4560','C4563','C4565','C4568','C456J','C4571','C4590','C459i','C459I','C5210','C5250','C5260','C5263','C526J','C52A0','C52C0','C5341','C5550','C5560','C5563','C556J','C55C0','C5610','C5630','C56A0','C5910','C5950','C5960','C5963','C596J','C7310','C7311','C7330','C7341','C7351','C7353','C735J','C7380','C73A0','C7510','C7550','C7560','C7563','C756J','C7570','C7571','C7590','C759I','C7610','C7710','C7800','C9510','C9550','C9560','C9563','C956J','C95C0')");
                    break;
//                case "OC":
//                    if("CELL1".equals(etlConfD.getCellType())){
//
//                    }else if("CELL2".equals(etlConfD.getCellType())){
//
//                    }
//                    break;
            }
            opes=dao2.findBySQL(opeSql.toString());
            if(opes.isEmpty()) opes.add(null);
        } catch (Exception e) {
            logger.error(LoggerUtil.stackTraceToString(e));
        }

        return opes;

    }

    public HashMap<String,EdaMeasureDefecttypeD> getDefectCodeTypeList(String shopOc) {
        String hql="from EdaMeasureDefecttypeD where shop='CELL2' and validFlg='Y'";
        HashMap<String,EdaMeasureDefecttypeD> defectCodeMap=new HashMap<>();
        try{
            List<EdaMeasureDefecttypeD> defectCodeList=mysqlDao.list(EdaMeasureDefecttypeD.class,hql);
            if(!defectCodeList.isEmpty())
                defectCodeList.forEach(e->defectCodeMap.put(e.getShop()+"_"+e.getDefectCode(),e));
        }catch (Exception e){
            throw new ETLException2(ErrorCode.ERROR_GET_MYSQL_DEFECTCODE_TYPE);
        }
        return defectCodeMap;
    }
}
